import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * @author shouhan
 * @version 1.0
 * @date 2018/10/9
 * @desc mybatis-plus代码生成器
 * 生成格式：com.vehicle.app.controller/service/dao.packageName.fileName
 * @see
 * @since 1.0
 */
public class MybatisPlusGenerator {

    //**************************运行时需要修改部分（begin）*******************************
    private static String project = "app";         //项目
    private static String packageName = "demo";    //包名
    private static String authorName = "shouhan";  //作者
    private static String table = "demo";          //表名
    private static String prefix = "";             //表的前缀
    //**************************运行时需要修改部分（end）*********************************
    private static File file = new File(project);
    private static String path = file.getAbsolutePath();

    /**
     * 入口run
     *
     * @param args
     */
    public static void main(String[] args) {
        String servicePath = path + "\\" + project + "-service";
        String apiPath = path + "\\" + project + "-api";

        // 代码生成器
        AutoGenerator serviceAutoGenerator = new AutoGenerator();
        serviceAutoGenerator.setGlobalConfig(getGlobalConfig(servicePath));
        serviceAutoGenerator.setDataSource(getDataSourceConfig());
        serviceAutoGenerator.setStrategy(getStrategy());
        serviceAutoGenerator.setPackageInfo(getPackageInfo());
        serviceAutoGenerator.setTemplate(getTemplateConfig());
        serviceAutoGenerator.setCfg(getInjectionConfig());
        // 执行生成
        serviceAutoGenerator.execute();

        // 代码生成器
        AutoGenerator apiAutoGenerator = new AutoGenerator();
        apiAutoGenerator.setGlobalConfig(getGlobalConfig(apiPath));
        apiAutoGenerator.setDataSource(getDataSourceConfig());
        apiAutoGenerator.setStrategy(getStrategy());
        apiAutoGenerator.setPackageInfo(getPackageInfo());
        apiAutoGenerator.setTemplate(getTemplateConfig());
        apiAutoGenerator.setCfg(getInjectionConfig());
        // 执行生成
        apiAutoGenerator.execute();

        // 打印注入设置，这里演示模板里面怎么获取注入内容【可无】
        //System.err.println("文件生成者：" + serviceAutoGenerator.getCfg().getMap().get("name"));
        //todo dubbo类型项目结构是两个项目生成 需要删除各自项目不需要的部分 待优化
        File file1 = new File(servicePath + "\\src\\main\\java\\com\\vehicle\\" + project + "\\api");
        File file2 = new File(servicePath + "\\src\\main\\java\\com\\vehicle\\" + project + "\\entity");
        File file3 = new File(apiPath + "\\src\\main\\java\\com\\vehicle\\" + project + "\\controller");
        File file4 = new File(apiPath + "\\src\\main\\java\\com\\vehicle\\" + project + "\\service");
        File file5 = new File(apiPath + "\\src\\main\\java\\com\\vehicle\\" + project + "\\dao");
        deleteFile(file1);
        deleteFile(file2);
        deleteFile(file3);
        deleteFile(file4);
        deleteFile(file5);
    }

    private static DataSourceConfig getDataSourceConfig() {
        // 数据源配置
        return new DataSourceConfig() {{
            // 数据库类型
            setDbType(DbType.MYSQL);
            setTypeConvert(new MySqlTypeConvert() {
                // 自定义数据库表字段类型转换【可选】
                @Override
                public DbColumnType processTypeConvert(String fieldType) {
                    System.out.println("转换类型：" + fieldType);
                    return super.processTypeConvert(fieldType);
                }
            });
            setDriverName("com.mysql.jdbc.Driver");
            setUsername("root");
            setPassword("123456");
            setUrl("jdbc:mysql://47.98.178.236:3306/vehicle?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true");
        }};
    }

    private static InjectionConfig getInjectionConfig() {
        // 注入自定义配置，可以在 VM 中使用 cfg.abc 设置的值
        return new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                map.put("name", this.getConfig().getGlobalConfig().getAuthor());
                this.setMap(map);
            }
        };


    }

    private static TemplateConfig getTemplateConfig() {
        // 关闭默认 xml 生成，调整生成 至 根目录
        return new TemplateConfig() {{
            setXml(null);
        }};
    }

    private static PackageConfig getPackageInfo() {
        // 包配置
        return new PackageConfig() {{
            // 自定义包路径
            setParent("com.vehicle.app");
            // 这里是控制器包名，默认 web
            setController("controller." + packageName);
            setEntity("entity." + packageName);
            setMapper("dao." + packageName);
            setService("api." + packageName);
            setServiceImpl("service." + packageName);
            //.setXml("mapper")
        }};
    }

    private static StrategyConfig getStrategy() {
        // 策略配置
        return new StrategyConfig() {{
            setTablePrefix(new String[]{prefix});
            // 表名生成策略
            setNaming(NamingStrategy.underline_to_camel);
            // 需要生成的表
            setInclude(new String[]{table});
            setRestControllerStyle(true);
        }};
    }

    private static GlobalConfig getGlobalConfig(String path) {
        //全局配置
        return new GlobalConfig() {{
            //输出目录
            setOutputDir(path + "/src/main/java");
            // 是否覆盖文件
            setFileOverride(false);
            // 开启 activeRecord 模式
            setActiveRecord(true);
            // XML 二级缓存
            setEnableCache(false);
            // XML ResultMap
            setBaseResultMap(true);
            // XML columList
            setBaseColumnList(true);
            //生成后打开文件夹
            setOpen(false);
            setAuthor(authorName);
            // 自定义文件命名，注意 %s 会自动填充表实体属性！
            setMapperName("%sMapper");
            setXmlName("%sMapper");
            setServiceName("I%sService");
            setServiceImplName("%sServiceImpl");
            setControllerName("%sController");
        }};
    }

    public static boolean deleteFile(File dirFile) {
        // 如果dir对应的文件不存在，则退出
        if (!dirFile.exists()) {
            return false;
        }

        if (dirFile.isFile()) {
            return dirFile.delete();
        } else {

            for (File file : dirFile.listFiles()) {
                deleteFile(file);
            }
        }

        return dirFile.delete();
    }


}
